/**
 * @fileOverview The "button" plugin.
 */
(function() {
   var template = '<a id="{id}"' +
      ' class="ved_button ved_button__{name} ved_button_{state} {cls}"' +
      ( VED.env.gecko && VED.env.version >= 10900 && !VED.env.hc ? '' : '" href="javascript:void(\'{titleJs}\')"' ) +
      ' title="{title}"' +
      ' tabindex="-1"' +
      ' hidefocus="true"' +
      ' role="button"' +
      ' aria-labelledby="{id}_label"' +
      ' aria-haspopup="{hasArrow}"';

   // Some browsers don't cancel key events in the keydown but in the
   // keypress.
   // TODO: Check if really needed for Gecko+Mac.
   if ( VED.env.opera || ( VED.env.gecko && VED.env.mac ) )
      template += ' onkeypress="return false;"';

   // With Firefox, we need to force the button to redraw, otherwise it
   // will remain in the focus state.
   if ( VED.env.gecko )
      template += ' onblur="this.style.cssText = this.style.cssText;"';

   template += ' onkeydown="return VED.tools.callFunction({keydownFn},event);"' +
      ' onfocus="return VED.tools.callFunction({focusFn},event);" ' +
      ' onmousedown="return VED.tools.callFunction({mousedownFn},event);" ' +
      ( VED.env.ie ? 'onclick="return false;" onmouseup' : 'onclick' ) + // #188
         '="VED.tools.callFunction({clickFn},this);return false;">' +
      '<span class="ved_button_icon ved_button__{iconName}_icon" style="{style}"';


   template += '>&nbsp;</span>' +
      '<span id="{id}_label" class="ved_button_label ved_button__{name}_label">{label}</span>' +
      '{arrowHtml}' +
      '</a>';

   var templateArrow = '<span class="ved_button_arrow">' +
      // BLACK DOWN-POINTING TRIANGLE
   ( VED.env.hc ? '&#9660;' : '' ) +
      '</span>';

   var btnArrowTpl = VED.addTemplate( 'buttonArrow', templateArrow ),
      btnTpl = VED.addTemplate( 'button', template );

   VED.plugins.add( 'button', {
      beforeInit: function( editor ) {
         editor.ui.addHandler( VED.UI_BUTTON, VED.ui.button.handler );
      }
   });

   VED.UI_BUTTON = 'button';

   /** @class VED.ui.button */
   VED.ui.button = new Class({
      initialize: function( definition ) {
         VED.tools.extend( this, definition, {
            // Set defaults.
            title: definition.label,
            click: definition.click ||
            function( editor ) {
               editor.execCommand( definition.command );
            }
         });

         this._ = {};
      },

      render: function( editor, output ) {
         var env = VED.env,
            id = this._.id = VED.tools.getNextId(),
            stateName = '',
            command = this.command,
            // Get the command name.
            clickFn;

         this._.editor = editor;

         var instance = {
            id: id,
            button: this,
            editor: editor,
            focus: function() {
               var element = VED.document.getById( id );
               element.focus();
            },
            execute: function() {
               this.button.click( editor );
            },
            attach: function( editor ) {
               this.button.attach( editor );
            }
         };

         var keydownFn = VED.tools.addFunction( function( ev ) {
            if ( instance.onkey ) {
               ev = new VED.dom.event( ev );
               return ( instance.onkey( instance, ev.getKeystroke() ) !== false );
            }
         });

         var focusFn = VED.tools.addFunction( function( ev ) {
            var retVal;

            if ( instance.onfocus )
               retVal = ( instance.onfocus( instance, new VED.dom.event( ev ) ) !== false );

            // FF2: prevent focus event been bubbled up to editor container, which caused unexpected editor focus.
            if ( VED.env.gecko && VED.env.version < 10900 )
               ev.preventBubble();
            return retVal;
         });

         var selLocked = 0;

         var mousedownFn = VED.tools.addFunction( function() {
            // Opera: lock to prevent loosing editable text selection when clicking on button.
            if ( VED.env.opera ) {
               var edt = editor.editable();
               if ( edt.isInline() && edt.hasFocus ) {
                  editor.lockSelection();
                  selLocked = 1;
               }
            }
         });

         instance.clickFn = clickFn = VED.tools.addFunction( function() {

            // Restore locked selection in Opera.
            if ( selLocked ) {
               editor.unlockSelection( 1 );
               selLocked = 0;
            }

            instance.execute();
         });


         // Indicate a mode sensitive button.
         if ( this.modes ) {
            var modeStates = {};

            function updateState() {
               // "this" is a VED.ui.button instance.

               var mode = editor.mode;

               if ( mode ) {
                  // Restore saved button state.
                  var state = this.modes[ mode ] ? modeStates[ mode ] != undefined ? modeStates[ mode ] : VED.TRISTATE_OFF : VED.TRISTATE_DISABLED;

                  this.setState( editor.readOnly && !this.readOnly ? VED.TRISTATE_DISABLED : state );
               }
            }

            editor.on( 'beforeModeUnload', function() {
               if ( editor.mode && this._.state != VED.TRISTATE_DISABLED )
                  modeStates[ editor.mode ] = this._.state;
            }, this );

            editor.on( 'mode', updateState, this );

            // If this button is sensitive to readOnly state, update it accordingly.
            !this.readOnly && editor.on( 'readOnly', updateState, this );
         } else if ( command ) {
            // Get the command instance.
            command = editor.getCommand( command );

            if ( command ) {
               command.on( 'state', function() {
                  this.setState( command.state );
               }, this );

               stateName += ( command.state == VED.TRISTATE_ON ? 'on' : command.state == VED.TRISTATE_DISABLED ? 'disabled' : 'off' );
            }
         }

         // For button that has text-direction awareness on selection path.
         if ( this.directional ) {
            editor.on( 'contentDirChanged', function( evt ) {
               var el = VED.document.getById( this._.id ),
                  icon = el.getFirst();

               var pathDir = evt.data;

               // Make a minor direction change to become style-able for the skin icon.
               if ( pathDir !=  editor.lang.dir )
                  el.addClass( 'ved_' + pathDir );
               else
                  el.removeClass( 'ved_ltr' ).removeClass( 'ved_rtl' );

               // Inline style update for the plugin icon.
               icon.setAttribute( 'style', VED.skin.getIconStyle( iconName, pathDir == 'rtl', this.icon, this.iconOffset ) );
            }, this );
         }

         if ( !command )
            stateName += 'off';

         var name = this.name || this.command,
            iconName = name;

         // Check if we're pointing to an icon defined by another command. (#9555)
         if ( this.icon && !( /\./ ).test( this.icon ) ) {
            iconName = this.icon;
            this.icon = null;
         }

         var params = {
            id: id,
            name: name,
            iconName: iconName,
            label: this.label,
            cls: this.className || '',
            state: stateName,
            title: this.title,
            titleJs: env.gecko && env.version >= 10900 && !env.hc ? '' : ( this.title || '' ).replace( "'", '' ),
            hasArrow: this.hasArrow ? 'true' : 'false',
            keydownFn: keydownFn,
            mousedownFn: mousedownFn,
            focusFn: focusFn,
            clickFn: clickFn,
            style: VED.skin.getIconStyle( iconName, ( editor.lang.dir == 'rtl' ), this.icon, this.iconOffset ),
            arrowHtml: this.hasArrow ? btnArrowTpl.output() : ''
         };

         btnTpl.output( params, output );

         if ( this.onRender )
            this.onRender();

         return instance;
      },

      setState: function( state ) {
         if ( this._.state == state )
            return false;

         this._.state = state;

         var element = VED.document.getById( this._.id );

         if ( element ) {
            element.setState( state, 'ved_button' );

            state == VED.TRISTATE_DISABLED ?
               element.setAttribute( 'aria-disabled', true ) :
               element.removeAttribute( 'aria-disabled' );

            state == VED.TRISTATE_ON ?
               element.setAttribute( 'aria-pressed', true ) :
               element.removeAttribute( 'aria-pressed' );

            return true;
         } else
            return false;
      },

      toFeature: function( editor ) {
         if ( this._.feature )
            return this._.feature;

         var feature = this;

         // If button isn't a feature, return command if is bound.
         if ( !this.allowedContent && !this.requiredContent && this.command )
            feature = editor.getCommand( this.command ) || feature;

         return this._.feature = feature;
      }

   });

   VED.ui.button.handler = {
      create: function( definition ) {
         return new VED.ui.button( definition );
      }
   };

   VED.ui.implement({
      addButton: function( name, definition ) {
         this.add( name, VED.UI_BUTTON, definition );
      }
   });


})();




